package App.OOSerVice.service;

import App.Model.ArisuDB;
import App.Model.Interface.MessageType;
import App.Model.User;
import App.Model.message.Message;
import App.OOSerVice.service.thread.ServiceFrameThread;
import App.OOSerVice.service.thread.StoCThread;
import App.OOSerVice.service.thread.manage.ManageStoCThread;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;

//服务器监听
public class OOService {
    //private static ConcurrentHashMap<String,User> validUsers = new ConcurrentHashMap<>();//可以处理并发(线程同步处理)多线程下安全
    public static HashMap<String, User> validUsers;//可能有风险

    static {
        //启动网站管理
        ServiceFrameThread thread = new ServiceFrameThread();
        thread.start();
        //加载ArisuDB数据库
        validUsers = ArisuDB.getUserMap();
        if (validUsers == null) {
            validUsers = new HashMap<>();
        }
    }

    private ServerSocket serverSocket = null;

    //验证用户有效性
    private boolean checkUserValid(String userId, String userPwd) {//可以根据需要增加在线状态验证: ManageCtoSThread中的Key
        User user = validUsers.get(userId);
        if (user != null) {
            if (user.getPassword().equals(userPwd)) {
                return true;
            }
        }
        return false;
    }

    public void QQServer() {
        try {
            serverSocket = new ServerSocket(9999);

            while (true) {//不断执行,当与一个客户端建立链接后,继续监听
                if(ArisuDB.isChange){
                    //当服务器数据发生改变时,重新设置用户数据
                    validUsers = ArisuDB.getUserMap();
                }
                Socket socket = serverSocket.accept();
                //读取对应输入流
                ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
                ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
                User user = (User) ois.readObject();
                Message message = new Message();

                System.out.println("userId: " + user.getUserId() + " || userPsw: " + user.getPassword());
                if (user.getUserName() != null && user.getUserName().equals("注册")) {
                    //当提交的为注册时,进行注册活动
                    System.out.println("注册行为");
                    User config = validUsers.get(user.getUserId());
                    if (config == null) {
                        //未有用户,注册成功
                        user.setUserName("新用户" + user.getUserId());
                        validUsers.put(user.getUserId(), user);
                        message.setMesType(MessageType.MESSAGE_SIGN_SUCCEED);
                        oos.writeObject(message);
                        //加入线程管理
                        StoCThread stoCThread = new StoCThread(user.getUserId(), socket);
                        stoCThread.start();
                        ManageStoCThread.addStoCThread(user.getUserId(), stoCThread);
                        //储存到ArisuDB中
                        ArisuDB.addUserMap(user.getUserId(), user);
                        ArisuDB.saveUserMapToFile();//返回bool值,可以在写入失败时打印日志
                        System.out.println("新用户注册 " + user.getUserId());
                    } else {
                        message.setMesType(MessageType.MESSAGE_SIGN_FAIL);
                        oos.writeObject(message);
                        //此处关闭必须在末尾,意味着任何尝试写入Socket的输出流的操作都会失败:即为oos与ois会一并失效
                        socket.close();
                    }
                } else if (checkUserValid(user.getUserId(), user.getPassword())) { //验证
                    if(ManageStoCThread.getStoCThread(user.getUserId()) == null){
                        //登录成功后操作
                        message.setMesType(MessageType.MESSAGE_LOGIN_SUCCEED);
                        oos.writeObject(message);
                        StoCThread stoCThread = new StoCThread(user.getUserId(), socket);
                        stoCThread.start();
                        //加入线程管理
                        ManageStoCThread.addStoCThread(user.getUserId(), stoCThread);
                    }else{
                        message.setMesType(MessageType.MESSAGE_LOGIN_FAIL_LOGGED);
                        oos.writeObject(message);
                    }
                } else {
                    //失败后操作
                    message.setMesType(MessageType.MESSAGE_LOGIN_FAIL);
                    oos.writeObject(message);
                    //此处关闭必须在末尾,意味着任何尝试写入Socket的输出流的操作都会失败:即为oos与ois会一并失效
                    socket.close();
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
